﻿using UnityEngine;
using System.Collections.Generic;
using TTGame;

/*
 * SkillRuntimeManager
 *
 * 提供技能运行时全局的管理，包括统计技能产生的子弹对技能属性的影响。（此时技能可能已经结束）
 * 主要是为了协调管理技能脚本中各个事件之间的逻辑。
 *
 * 使用情形：
 * 1、技能对于同一对象的重复伤害判定。
 *
 *      伤害是由子弹产生，而子弹是独立于技能的，当子弹碰撞时技能可能已经销毁或者开始释放下一个技能。
 *
 * 2、技能携带Buff，之后的触发框会触发该Buff。
 *
 * 依赖：
 *
 * ！不写重复代码！
 * @author TTun
 * @date 8/14/2017 11:43:32 AM
 */
namespace TTGameEngine {
//当检测到目标时。
public delegate void OnSkillHarmTarget(SkillTL skillTL, Puppet target);
public delegate void DamageHandler(Puppet reciver, DamageInfo dmgInfo);

/// <summary>
/// 处理Skill施放后的逻辑。独立于Skill，携带逻辑所用到的Skill参数。即使skill结束，依然存在，直到所有子弹结束。
/// </summary>
public class SkillHandler {
    //技能的伤害列表
    Dictionary<string, int> harmObjList = new Dictionary<string, int>();
    //该技能产生的子弹，所有的子弹都销毁的话，技能逻辑就可以结束了。
    public List<MagicBall> m_bullets = new List<MagicBall>();
    //逻辑所需要的技能参数
    public uint m_castID;
    public SkillData m_skillData;
    protected List<int> m_buffIDs = new List<int>();

    OnSkillHarmTarget m_onSkillHarmTarget;
    bool m_isSkillEnd;
    bool m_isLogicEnd;

    public SkillHandler(uint castID, SkillData skillData) {
        m_castID = castID;
        m_skillData = skillData;
        m_isSkillEnd = false;
        m_isLogicEnd = false;
    }

    public List<int> BuffIDs {
        get { return m_buffIDs; }
    }

    public void RegistBullet(MagicBall mb) {
#if UNITY_EDITOR
        if(m_bullets.Contains(mb)) {
            DebugUtil.LogErrorFormat("[SkillHandler]name:[{0}] 重复添加子弹.bullet:[{1}]", m_skillData.skillName, mb.name);
        }
#endif
        mb.CB_MagicBallDeactive += onMagicBallDeactive;
        m_bullets.Add(mb);
        mb.SetDamageHandler(GetDamageHandler());
    }

    public void onMagicBallDeactive(MagicBall mb) {
#if UNITY_EDITOR
        if(m_bullets.Contains(mb) == false) {
            DebugUtil.LogErrorFormat("[SkillHandler]name:[{0}] 删除子弹失败，子弹不存在.bullet:[{1}]", m_skillData.skillName, mb.name);
        }
#endif
        m_bullets.Remove(mb);
        if(m_isSkillEnd && m_bullets.Count == 0) {
            m_isLogicEnd = true;
        }
    }

    //技能结束，不会再有新的一级子弹产生。但有可能有新的二级子弹。
    public void SetSkillEnd() {
        m_isSkillEnd = true;
        if(m_bullets.Count == 0) {
            m_isLogicEnd = true;
        }
    }

    public void RegistCB_SkillDetectTarget(OnSkillHarmTarget cb) {
        m_onSkillHarmTarget += cb;
    }

    public void UnRegistCB_SkillDetectTarget(OnSkillHarmTarget cb) {
        m_onSkillHarmTarget -= cb;
    }

    void handlerHurtType(Puppet target, DamageInfo dmgInfo) {
        HurtType hurtType = m_skillData.m_hurtType;
        //判断受伤方向  cosθ = (a.b)/|a||b| (假设a、b是单位向量，长度为1)   cosθ>0夹角小于90， cosθ<0夹角大于90
        Vector3 va = target.objTF.forward;
        Vector3 vb = dmgInfo.hitPointOffset;
        float cosA = Vector3.Dot(va, vb);
        if(cosA > 0) {
            //正面受伤
            dmgInfo.isHurtForward = true;
        } else {
            //背面受伤
            dmgInfo.isHurtForward = false;
        }
        dmgInfo.hurtType = hurtType;
    }

    /// <summary>
    /// 检查是否是重复伤害。
    ///
    /// X 重复伤害由单个子弹碰撞处理。一个技能既然有多个子弹，那肯定要有多个碰撞伤害。
    /// </summary>
    /// <param name="objGID"></param>
    /// <returns>是否可以造成伤害</returns>
    bool CheckCastDamage(string objGID) {
        bool isHarm = false;
        if(harmObjList.ContainsKey(objGID)) {
            DebugUtil.LogWarningFormat("[Skill] harm repeat, skip damage. obj:[{0}]", objGID);
        } else {
            harmObjList.Add(objGID, 1);
            isHarm = true;
        }

        return isHarm;
    }

    /// <summary>
    /// 统一处理技能产生的子弹所产生的伤害。
    /// </summary>
    public void TriggerDamageHandler(Puppet target, DamageInfo dmgInfo) {
        //if(CheckCastDamage(target.GetGID())) {
        handlerHurtType(target, dmgInfo);
        target.ApplyDamage(dmgInfo);
        if(m_onSkillHarmTarget != null) m_onSkillHarmTarget(null, target);
        //}
    }

    public DamageHandler GetDamageHandler() {
        return TriggerDamageHandler;
    }

    public int GetHarmObjsCount() {
        return harmObjList.Count;
    }

    /// <summary>
    /// 该技能绑定Buff，之后的触发框都会触发该Buff。
    /// </summary>
    /// <param name="buffID"></param>
    public void BindSkillBuff(int buffID) {
#if UNITY_EDITOR
        if(m_buffIDs.Contains(buffID)) {
            DebugUtil.LogErrorFormat("[SkillHandler]name:[{0}] 重复绑定Buff. buffID:[{1}]", m_skillData.skillName, buffID);
        }
#endif
        m_buffIDs.Add(buffID);
    }

    public void CancelSkillBuff(int buffID) {
        m_buffIDs.Remove(buffID);
    }

}

}